<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数独游戏</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#3B82F6',
                        secondary: '#10B981',
                        accent: '#F59E0B',
                        dark: '#1F2937',
                        light: '#F3F4F6'
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .cell-border {
                @apply border border-gray-300;
            }
            .cell-highlight {
                @apply bg-blue-100 transition-colors duration-200;
            }
            .cell-selected {
                @apply bg-blue-200 transition-colors duration-200;
            }
            .cell-error {
                @apply bg-red-100 transition-colors duration-200;
            }
            .btn-hover {
                @apply hover:shadow-lg transform hover:-translate-y-0.5 transition-all duration-200;
            }
            .grid-line {
                @apply border-b-2 border-r-2 border-gray-600;
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-light to-gray-200 min-h-screen font-sans">
    <div class="container mx-auto px-4 py-8 max-w-4xl">
        <!-- 顶部标题区域 -->
        <header class="text-center mb-8">
            <h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold text-dark mb-2 tracking-tight">
                <span class="text-primary">数</span><span class="text-accent">独</span>
                <span class="text-[clamp(1rem,2vw,1.5rem)] font-normal text-gray-600 ml-2">Sudoku</span>
            </h1>
            <p class="text-gray-600 max-w-2xl mx-auto">锻炼逻辑思维的经典数字游戏，将数字1-9填入空格，使每行、每列和每个3x3小九宫格内均不重复。</p>
        </header>

        <!-- 游戏区域 -->
        <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
            <!-- 左侧：游戏信息 -->
            <div class="lg:col-span-1 order-2 lg:order-1">
                <div class="bg-white rounded-xl shadow-lg p-6 h-full flex flex-col">
                    <div class="mb-6">
                        <h2 class="text-xl font-bold text-dark mb-3 flex items-center">
                            <i class="fa fa-trophy text-accent mr-2"></i>游戏进度
                        </h2>
                        <div class="grid grid-cols-2 gap-4 mb-4">
                            <div class="bg-gray-50 rounded-lg p-4 text-center">
                                <p class="text-sm text-gray-500 mb-1">已用时</p>
                                <p id="timer" class="text-2xl font-bold text-primary">00:00</p>
                            </div>
                            <div class="bg-gray-50 rounded-lg p-4 text-center">
                                <p class="text-sm text-gray-500 mb-1">完成度</p>
                                <p id="progress" class="text-2xl font-bold text-secondary">0%</p>
                            </div>
                        </div>
                        <div class="bg-gray-50 rounded-lg p-4">
                            <p class="text-sm text-gray-500 mb-1">难度</p>
                            <div class="flex items-center">
                                <select id="difficulty" class="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50">
                                    <option value="easy">简单</option>
                                    <option value="medium" selected>中等</option>
                                    <option value="hard">困难</option>
                                    <option value="expert">专家</option>
                                </select>
                            </div>
                        </div>
                    </div>

                    <div class="mb-6">
                        <h2 class="text-xl font-bold text-dark mb-3 flex items-center">
                            <i class="fa fa-info-circle text-primary mr-2"></i>游戏说明
                        </h2>
                        <ul class="text-gray-600 space-y-2 text-sm">
                            <li class="flex items-start">
                                <i class="fa fa-check-circle text-secondary mt-1 mr-2"></i>
                                <span>点击单元格后，使用数字键盘输入1-9</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fa fa-check-circle text-secondary mt-1 mr-2"></i>
                                <span>错误的数字会显示为红色</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fa fa-check-circle text-secondary mt-1 mr-2"></i>
                                <span>点击"清除"按钮删除当前选中单元格的数字</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fa fa-check-circle text-secondary mt-1 mr-2"></i>
                                <span>点击"提示"按钮获取一个正确数字</span>
                            </li>
                        </ul>
                    </div>

                    <div class="mt-auto">
                        <div class="grid grid-cols-2 gap-3">
                            <button id="new-game" class="bg-primary hover:bg-primary/90 text-white py-3 px-4 rounded-lg font-medium flex items-center justify-center btn-hover">
                                <i class="fa fa-refresh mr-2"></i>新游戏
                            </button>
                            <button id="hint" class="bg-accent hover:bg-accent/90 text-white py-3 px-4 rounded-lg font-medium flex items-center justify-center btn-hover">
                                <i class="fa fa-lightbulb-o mr-2"></i>提示
                            </button>
                        </div>
                        <button id="solve" class="w-full mt-3 bg-secondary hover:bg-secondary/90 text-white py-3 px-4 rounded-lg font-medium flex items-center justify-center btn-hover">
                            <i class="fa fa-magic mr-2"></i>显示答案
                        </button>
                    </div>
                </div>
            </div>

            <!-- 右侧：数独棋盘 -->
            <div class="lg:col-span-2 order-1 lg:order-2">
                <div class="bg-white rounded-xl shadow-lg p-6">
                    <div class="flex justify-between items-center mb-4">
                        <h2 class="text-xl font-bold text-dark flex items-center">
                            <i class="fa fa-th text-primary mr-2"></i>数独棋盘
                        </h2>
                        <div class="flex space-x-2">
                            <button id="clear" class="bg-gray-200 hover:bg-gray-300 text-gray-800 py-2 px-4 rounded-lg font-medium btn-hover">
                                <i class="fa fa-eraser mr-1"></i>清除
                            </button>
                            <button id="check" class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded-lg font-medium btn-hover">
                                <i class="fa fa-check mr-1"></i>检查
                            </button>
                        </div>
                    </div>

                    <!-- 数独棋盘 -->
                    <div class="flex justify-center mb-6">
                        <div id="sudoku-grid" class="grid grid-cols-9 grid-rows-9 border-2 border-gray-600 rounded-md overflow-hidden">
                            <!-- 数独单元格将由JavaScript动态生成 -->
                        </div>
                    </div>

                    <!-- 数字选择器 -->
                    <div id="number-pad" class="grid grid-cols-9 gap-2 max-w-md mx-auto mb-2">
                        <!-- 数字按钮将由JavaScript动态生成 -->
                    </div>

                    <!-- 游戏结果弹窗 -->
                    <div id="result-modal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden opacity-0 transition-opacity duration-300">
                        <div class="bg-white rounded-xl shadow-2xl p-8 max-w-md w-full mx-4 transform transition-transform duration-300 scale-95">
                            <div class="text-center">
                                <div id="result-icon" class="text-6xl mb-4"></div>
                                <h2 id="result-title" class="text-2xl font-bold mb-2"></h2>
                                <p id="result-message" class="text-gray-600 mb-6"></p>
                                <button id="play-again" class="bg-primary hover:bg-primary/90 text-white py-3 px-8 rounded-lg font-medium btn-hover">
                                    再玩一次
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 页脚 -->
        <footer class="mt-12 text-center text-gray-500 text-sm">
            <p>数独游戏 | 锻炼逻辑思维的经典数字游戏</p>
        </footer>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 游戏状态
            let board = []; // 存储完整的数独解
            let puzzle = []; // 存储当前谜题（用户看到的）
            let solution = []; // 存储正确答案
            let selectedCell = null; // 当前选中的单元格
            let timer = null; // 计时器
            let timeElapsed = 0; // 已用时间（秒）
            let gameStarted = false; // 游戏是否已开始

            // 初始化数独棋盘
            function initializeBoard() {
                const grid = document.getElementById('sudoku-grid');
                grid.innerHTML = '';
                
                // 创建81个单元格
                for (let i = 0; i < 81; i++) {
                    const row = Math.floor(i / 9);
                    const col = i % 9;
                    
                    // 计算单元格样式（处理3x3网格的粗线）
                    let cellClass = 'cell-border w-10 h-10 md:w-12 md:h-12 flex items-center justify-center text-lg md:text-xl font-medium';
                    
                    // 3x3网格分隔线
                    if (row === 2 || row === 5) cellClass += ' border-b-2';
                    if (col === 2 || col === 5) cellClass += ' border-r-2';
                    
                    const cell = document.createElement('div');
                    cell.id = `cell-${row}-${col}`;
                    cell.className = cellClass;
                    cell.dataset.row = row;
                    cell.dataset.col = col;
                    
                    // 单元格点击事件
                    cell.addEventListener('click', () => selectCell(row, col));
                    
                    grid.appendChild(cell);
                }
                
                // 创建数字选择器
                const numberPad = document.getElementById('number-pad');
                numberPad.innerHTML = '';
                
                for (let i = 1; i <= 9; i++) {
                    const button = document.createElement('button');
                    button.className = 'bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-md h-10 flex items-center justify-center font-bold transition-colors duration-200';
                    button.textContent = i;
                    
                    // 数字按钮点击事件
                    button.addEventListener('click', () => {
                        if (selectedCell) {
                            const row = selectedCell.dataset.row;
                            const col = selectedCell.dataset.col;
                            fillCell(row, col, i);
                        }
                    });
                    
                    numberPad.appendChild(button);
                }
            }

            // 选择单元格
            function selectCell(row, col) {
                // 取消之前选中的单元格
                if (selectedCell) {
                    selectedCell.classList.remove('cell-selected');
                }
                
                // 选择新单元格
                selectedCell = document.getElementById(`cell-${row}-${col}`);
                
                // 如果是预填的数字，不允许选择
                if (selectedCell.classList.contains('text-gray-800')) {
                    selectedCell = null;
                    return;
                }
                
                // 高亮新选中的单元格
                if (selectedCell) {
                    selectedCell.classList.add('cell-selected');
                    
                    // 高亮同行、同列和同一个3x3网格的单元格
                    highlightRelatedCells(row, col);
                }
            }

            // 高亮相关单元格
            function highlightRelatedCells(row, col) {
                // 清除之前的高亮
                document.querySelectorAll('.cell-highlight').forEach(cell => {
                    cell.classList.remove('cell-highlight');
                });
                
                // 高亮同行、同列和同一个3x3网格的单元格
                for (let i = 0; i < 9; i++) {
                    // 同行
                    const rowCell = document.getElementById(`cell-${row}-${i}`);
                    if (rowCell !== selectedCell && !rowCell.classList.contains('text-gray-800')) {
                        rowCell.classList.add('cell-highlight');
                    }
                    
                    // 同列
                    const colCell = document.getElementById(`cell-${i}-${col}`);
                    if (colCell !== selectedCell && !colCell.classList.contains('text-gray-800')) {
                        colCell.classList.add('cell-highlight');
                    }
                }
                
                // 同一个3x3网格
                const startRow = Math.floor(row / 3) * 3;
                const startCol = Math.floor(col / 3) * 3;
                
                for (let i = startRow; i < startRow + 3; i++) {
                    for (let j = startCol; j < startCol + 3; j++) {
                        const cell = document.getElementById(`cell-${i}-${j}`);
                        if (cell !== selectedCell && !cell.classList.contains('text-gray-800')) {
                            cell.classList.add('cell-highlight');
                        }
                    }
                }
            }

            // 填充单元格
            function fillCell(row, col, number) {
                if (puzzle[row][col] !== 0) return; // 如果单元格已经有数字，不填充
                
                const cell = document.getElementById(`cell-${row}-${col}`);
                cell.textContent = number;
                cell.classList.add('text-primary');
                
                // 检查是否与答案一致
                if (number === solution[row][col]) {
                    cell.classList.remove('cell-error');
                    puzzle[row][col] = number;
                } else {
                    cell.classList.add('cell-error');
                }
                
                // 检查游戏是否完成
                checkGameCompletion();
            }

            // 清除单元格
            function clearCell(row, col) {
                const cell = document.getElementById(`cell-${row}-${col}`);
                if (cell.classList.contains('text-gray-800')) return; // 如果是预填的数字，不清除
                
                cell.textContent = '';
                cell.classList.remove('text-primary', 'cell-error');
                puzzle[row][col] = 0;
            }

            // 生成新的数独游戏
            function generateNewGame(difficulty = 'medium') {
                // 停止之前的计时器
                if (timer) {
                    clearInterval(timer);
                    timer = null;
                }
                
                // 重置游戏状态
                timeElapsed = 0;
                document.getElementById('timer').textContent = '00:00';
                document.getElementById('progress').textContent = '0%';
                gameStarted = true;
                
                // 生成完整的数独解
                solution = generateSolution();
                board = JSON.parse(JSON.stringify(solution));
                
                // 根据难度移除一些数字生成谜题
                puzzle = removeNumbers(board, difficulty);
                
                // 渲染数独谜题
                renderPuzzle();
                
                // 开始计时
                startTimer();
                
                // 隐藏结果弹窗
                hideResultModal();
            }

            // 生成完整的数独解
            function generateSolution() {
                const solution = Array(9).fill().map(() => Array(9).fill(0));
                
                // 使用回溯法生成数独解
                function backtrack(row, col) {
                    if (row === 9) return true;
                    
                    const nextRow = col === 8 ? row + 1 : row;
                    const nextCol = col === 8 ? 0 : col + 1;
                    
                    // 随机尝试数字1-9
                    const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
                    shuffleArray(numbers);
                    
                    for (const num of numbers) {
                        if (isValid(solution, row, col, num)) {
                            solution[row][col] = num;
                            
                            if (backtrack(nextRow, nextCol)) {
                                return true;
                            }
                            
                            solution[row][col] = 0;
                        }
                    }
                    
                    return false;
                }
                
                backtrack(0, 0);
                return solution;
            }

            // 检查数字是否可以放在指定位置
            function isValid(grid, row, col, num) {
                // 检查行
                for (let i = 0; i < 9; i++) {
                    if (grid[row][i] === num) return false;
                }
                
                // 检查列
                for (let i = 0; i < 9; i++) {
                    if (grid[i][col] === num) return false;
                }
                
                // 检查3x3网格
                const startRow = Math.floor(row / 3) * 3;
                const startCol = Math.floor(col / 3) * 3;
                
                for (let i = startRow; i < startRow + 3; i++) {
                    for (let j = startCol; j < startCol + 3; j++) {
                        if (grid[i][j] === num) return false;
                    }
                }
                
                return true;
            }

            // 随机打乱数组
            function shuffleArray(array) {
                for (let i = array.length - 1; i > 0; i--) {
                    const j = Math.floor(Math.random() * (i + 1));
                    [array[i], array[j]] = [array[j], array[i]];
                }
            }

            // 根据难度移除一些数字
            function removeNumbers(board, difficulty) {
                const puzzle = JSON.parse(JSON.stringify(board));
                let cellsToRemove = 0;
                
                // 根据难度确定要移除的数字数量
                switch(difficulty) {
                    case 'easy':
                        cellsToRemove = 30;
                        break;
                    case 'medium':
                        cellsToRemove = 40;
                        break;
                    case 'hard':
                        cellsToRemove = 50;
                        break;
                    case 'expert':
                        cellsToRemove = 60;
                        break;
                    default:
                        cellsToRemove = 40;
                }
                
                // 随机选择要移除的单元格
                const cells = [];
                for (let i = 0; i < 81; i++) {
                    cells.push(i);
                }
                shuffleArray(cells);
                
                // 移除选定的单元格
                for (let i = 0; i < cellsToRemove; i++) {
                    const cell = cells[i];
                    const row = Math.floor(cell / 9);
                    const col = cell % 9;
                    puzzle[row][col] = 0;
                }
                
                return puzzle;
            }

            // 渲染数独谜题
            function renderPuzzle() {
                for (let i = 0; i < 9; i++) {
                    for (let j = 0; j < 9; j++) {
                        const cell = document.getElementById(`cell-${i}-${j}`);
                        
                        if (puzzle[i][j] !== 0) {
                            cell.textContent = puzzle[i][j];
                            cell.classList.add('text-gray-800');
                        } else {
                            cell.textContent = '';
                            cell.classList.remove('text-gray-800', 'text-primary', 'cell-error');
                        }
                    }
                }
                
                // 重置选中单元格
                if (selectedCell) {
                    selectedCell.classList.remove('cell-selected');
                    selectedCell = null;
                }
                
                // 清除高亮
                document.querySelectorAll('.cell-highlight').forEach(cell => {
                    cell.classList.remove('cell-highlight');
                });
            }

            // 开始计时器
            function startTimer() {
                if (timer) clearInterval(timer);
                
                timer = setInterval(() => {
                    timeElapsed++;
                    updateTimerDisplay();
                }, 1000);
            }

            // 更新计时器显示
            function updateTimerDisplay() {
                const minutes = Math.floor(timeElapsed / 60).toString().padStart(2, '0');
                const seconds = (timeElapsed % 60).toString().padStart(2, '0');
                document.getElementById('timer').textContent = `${minutes}:${seconds}`;
            }

            // 检查游戏是否完成
            function checkGameCompletion() {
                for (let i = 0; i < 9; i++) {
                    for (let j = 0; j < 9; j++) {
                        if (puzzle[i][j] === 0 || puzzle[i][j] !== solution[i][j]) {
                            updateProgress();
                            return false;
                        }
                    }
                }
                
                // 游戏完成
                clearInterval(timer);
                timer = null;
                showResultModal(true);
                return true;
            }

            // 更新完成度
            function updateProgress() {
                let filledCells = 0;
                const totalCells = 81;
                
                for (let i = 0; i < 9; i++) {
                    for (let j = 0; j < 9; j++) {
                        if (puzzle[i][j] !== 0) {
                            filledCells++;
                        }
                    }
                }
                
                const progress = Math.round((filledCells / totalCells) * 100);
                document.getElementById('progress').textContent = `${progress}%`;
            }

            // 显示提示
            function showHint() {
                if (!gameStarted) return;
                
                // 找到一个空单元格
                let emptyCells = [];
                for (let i = 0; i < 9; i++) {
                    for (let j = 0; j < 9; j++) {
                        if (puzzle[i][j] === 0) {
                            emptyCells.push({ row: i, col: j });
                        }
                    }
                }
                
                if (emptyCells.length === 0) return;
                
                // 随机选择一个空单元格
                const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
                const { row, col } = randomCell;
                
                // 填入正确的数字
                fillCell(row, col, solution[row][col]);
                
                // 选中这个单元格
                selectCell(row, col);
            }

            // 显示答案
            function showSolution() {
                if (!gameStarted) return;
                
                for (let i = 0; i < 9; i++) {
                    for (let j = 0; j < 9; j++) {
                        if (puzzle[i][j] === 0) {
                            fillCell(i, j, solution[i][j]);
                        }
                    }
                }
                
                // 停止计时器
                clearInterval(timer);
                timer = null;
            }

            // 检查答案
            function checkSolution() {
                if (!gameStarted) return;
                
                let hasError = false;
                
                for (let i = 0; i < 9; i++) {
                    for (let j = 0; j < 9; j++) {
                        const cell = document.getElementById(`cell-${i}-${j}`);
                        
                        // 跳过预填的单元格
                        if (cell.classList.contains('text-gray-800')) continue;
                        
                        // 检查非空单元格
                        if (puzzle[i][j] !== 0) {
                            if (puzzle[i][j] !== solution[i][j]) {
                                cell.classList.add('cell-error');
                                hasError = true;
                            } else {
                                cell.classList.remove('cell-error');
                            }
                        }
                    }
                }
                
                // 如果没有错误，检查是否完成
                if (!hasError && checkGameCompletion()) {
                    showResultModal(true);
                } else if (hasError) {
                    showResultModal(false);
                }
            }

            // 显示结果弹窗
            function showResultModal(isSuccess) {
                const modal = document.getElementById('result-modal');
                const icon = document.getElementById('result-icon');
                const title = document.getElementById('result-title');
                const message = document.getElementById('result-message');
                
                if (isSuccess) {
                    icon.className = 'fa fa-trophy text-6xl text-accent mb-4';
                    title.textContent = '恭喜你！';
                    title.className = 'text-2xl font-bold mb-2 text-secondary';
                    message.textContent = `你完成了数独游戏，用时 ${Math.floor(timeElapsed / 60)} 分 ${timeElapsed % 60} 秒。`;
                } else {
                    icon.className = 'fa fa-times-circle text-6xl text-red-500 mb-4';
                    title.textContent = '再试一次';
                    title.className = 'text-2xl font-bold mb-2 text-red-600';
                    message.textContent = '你的答案中包含错误，请检查后继续。';
                }
                
                // 显示弹窗并添加动画
                modal.classList.remove('hidden');
                setTimeout(() => {
                    modal.classList.add('opacity-100');
                    modal.querySelector('div').classList.add('scale-100');
                    modal.querySelector('div').classList.remove('scale-95');
                }, 10);
            }

            // 隐藏结果弹窗
            function hideResultModal() {
                const modal = document.getElementById('result-modal');
                modal.classList.remove('opacity-100');
                modal.querySelector('div').classList.remove('scale-100');
                modal.querySelector('div').classList.add('scale-95');
                
                setTimeout(() => {
                    modal.classList.add('hidden');
                }, 300);
            }

            // 事件监听
            document.getElementById('new-game').addEventListener('click', () => {
                const difficulty = document.getElementById('difficulty').value;
                generateNewGame(difficulty);
            });
            
            document.getElementById('hint').addEventListener('click', showHint);
            document.getElementById('solve').addEventListener('click', showSolution);
            document.getElementById('clear').addEventListener('click', () => {
                if (selectedCell) {
                    const row = selectedCell.dataset.row;
                    const col = selectedCell.dataset.col;
                    clearCell(row, col);
                }
            });
            document.getElementById('check').addEventListener('click', checkSolution);
            document.getElementById('play-again').addEventListener('click', () => {
                const difficulty = document.getElementById('difficulty').value;
                generateNewGame(difficulty);
            });
            
            // 键盘事件监听
            document.addEventListener('keydown', (e) => {
                if (!selectedCell) return;
                
                const row = parseInt(selectedCell.dataset.row);
                const col = parseInt(selectedCell.dataset.col);
                
                // 数字键1-9
                if (e.key >= '1' && e.key <= '9') {
                    fillCell(row, col, parseInt(e.key));
                }
                
                // 删除键或退格键
                if (e.key === 'Delete' || e.key === 'Backspace') {
                    clearCell(row, col);
                }
                
                // 方向键移动选中单元格
                if (e.key === 'ArrowUp' && row > 0) {
                    selectCell(row - 1, col);
                } else if (e.key === 'ArrowDown' && row < 8) {
                    selectCell(row + 1, col);
                } else if (e.key === 'ArrowLeft' && col > 0) {
                    selectCell(row, col - 1);
                } else if (e.key === 'ArrowRight' && col < 8) {
                    selectCell(row, col + 1);
                }
            });

            // 初始化游戏
            initializeBoard();
            generateNewGame();
        });
    </script>
</body>
</html>
    